#pragma once

#include <efi/efi.hpp>

#include <audio/audio.hpp>

//
// RIFF chunk IDs.
//
#define RIFF_CHUNK_ID_SIZE 4
#define RIFF_CHUNK_ID "RIFF"
#define LIST_CHUNK_ID "LIST"
#define PAL_CHUNK_ID "PAL "
#define RDIB_CHUNK_ID "RDIB"
#define RMID_CHUNK_ID "RMID"
#define RMMP_CHUNK_ID "RMMP"

//
// WAVE chunk IDs.
//
#define WAVE_CHUNK_ID "WAVE"
#define WAVE_CUE_CHUNK_ID "cue "
#define WAVE_DATA_CHUNK_ID "data"
#define WAVE_FACT_CHUNK_ID "fact"
#define WAVE_FILE_CHUNK_ID "file"
#define WAVE_FORMAT_CHUNK_ID "fmt "
#define WAVE_LABEL_CHUNK_ID "labl"
#define WAVE_NOTE_CHUNK_ID "note"
#define WAVE_PLAYLIST_CHUNK_ID "plst"
#define WAVE_SILENCE_CHUNK_ID "slnt"
#define WAVE_TEXT_DATA_CHUNK_ID "ltxt"
#define WAVE_WAVE_LIST_CHUNK_ID "wavl"

//
// WAVE format types.
//
#define WAVE_FORMAT_PCM 0x0001
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE

namespace audio::Riff {

#pragma pack(1)

// RIFF chunk.
typedef struct {
  char id[RIFF_CHUNK_ID_SIZE];
  uint32_t size;
  uint8_t data[];
} RiffChunk;

// WAVE format data.
typedef struct {
  uint16_t formatTag;
  uint16_t channels;
  uint32_t samplesPerSec;
  uint32_t avgBytesPerSec;
  uint16_t blockAlign;
  uint16_t bitsPerSample;
} WaveFormatData;

// WAVE format data extended.
typedef struct {
  WaveFormatData header;
  uint16_t extensionSize;
  uint16_t validBitsPerSample;
  uint32_t channelMask;
  efi::Guid subFormat;
} WaveFormatDataEx;

typedef struct {
  uint64_t fileLength;
  uint32_t dataLength;

  WaveFormatData *format;
  uint32_t formatLength;

  uint8_t *samples;
  uint32_t samplesLength;
} WaveFile;

#pragma pack()

audio::Audio readFromFile(const char16_t *path);

} // namespace audio::Riff
